const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');

const RoomManager = require('./roomManager');
const WebSocketServer = require('./websocketServer');
const ApiRouter = require('./apiRouter');

/**
 * Main HTTP server for the chat application
 */
class ChatServer {
    constructor(port = 3000) {
        this.port = port;
        this.roomManager = new RoomManager();
        this.apiRouter = new ApiRouter(this.roomManager);
        this.server = null;
        this.websocketServer = null;
        
        this.setupServer();
    }

    /**
     * Setup HTTP server
     */
    setupServer() {
        this.server = http.createServer((req, res) => {
            this.handleRequest(req, res);
        });

        // Setup WebSocket server
        this.websocketServer = new WebSocketServer(this.server, this.roomManager);
        
        // Start health check for WebSocket connections
        this.websocketServer.startHealthCheck();
        
        // Start periodic maintenance
        setInterval(() => {
            this.roomManager.performMaintenance();
        }, 60000); // Every minute
    }

    /**
     * Handle HTTP requests
     */
    async handleRequest(req, res) {
        const parsedUrl = url.parse(req.url, true);
        const pathname = parsedUrl.pathname;

        try {
            // API routes
            if (pathname.startsWith('/api/')) {
                await this.apiRouter.handleRequest(req, res);
                return;
            }

            // Static file serving
            await this.serveStaticFile(req, res, pathname);
            
        } catch (error) {
            console.error('Server error:', error);
            this.sendError(res, 500, 'Internal server error');
        }
    }

    /**
     * Serve static files
     */
    async serveStaticFile(req, res, pathname) {
        // Handle specific page routes
        if (pathname === '/') {
            pathname = '/index.html';
        } else if (pathname === '/room.html') {
            pathname = '/room.html';
        }
        // Remove SPA fallback - no more catch-all routing to index.html

        const filePath = path.join(__dirname, '..', 'public', pathname);
        const extname = path.extname(filePath).toLowerCase();

        // Security check - prevent directory traversal
        const publicDir = path.join(__dirname, '..', 'public');
        const resolvedPath = path.resolve(filePath);
        if (!resolvedPath.startsWith(publicDir)) {
            this.sendError(res, 403, 'Forbidden');
            return;
        }

        try {
            const stats = await fs.promises.stat(filePath);
            
            if (stats.isFile()) {
                const contentType = this.getContentType(extname);
                const content = await fs.promises.readFile(filePath);
                
                res.writeHead(200, {
                    'Content-Type': contentType,
                    'Content-Length': content.length,
                    'Cache-Control': 'public, max-age=3600' // Cache for 1 hour
                });
                res.end(content);
            } else {
                this.sendError(res, 404, 'File not found');
            }
        } catch (error) {
            if (error.code === 'ENOENT') {
                this.sendError(res, 404, 'File not found');
            } else {
                console.error('File serving error:', error);
                this.sendError(res, 500, 'Internal server error');
            }
        }
    }

    /**
     * Get content type based on file extension
     */
    getContentType(extname) {
        const mimeTypes = {
            '.html': 'text/html',
            '.css': 'text/css',
            '.js': 'text/javascript',
            '.json': 'application/json',
            '.png': 'image/png',
            '.jpg': 'image/jpg',
            '.jpeg': 'image/jpeg',
            '.gif': 'image/gif',
            '.svg': 'image/svg+xml',
            '.ico': 'image/x-icon',
            '.woff': 'font/woff',
            '.woff2': 'font/woff2',
            '.ttf': 'font/ttf',
            '.eot': 'application/vnd.ms-fontobject'
        };

        return mimeTypes[extname] || 'application/octet-stream';
    }

    /**
     * Send error response
     */
    sendError(res, statusCode, message) {
        res.writeHead(statusCode, {
            'Content-Type': 'text/html'
        });
        res.end(`
            <!DOCTYPE html>
            <html>
            <head>
                <title>Error ${statusCode}</title>
                <style>
                    body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
                    .error { color: #d32f2f; }
                </style>
            </head>
            <body>
                <h1 class="error">Error ${statusCode}</h1>
                <p>${message}</p>
                <a href="/">Return to Home</a>
            </body>
            </html>
        `);
    }

    /**
     * Start the server
     */
    start() {
        return new Promise((resolve, reject) => {
            this.server.listen(this.port, (error) => {
                if (error) {
                    reject(error);
                    return;
                }

                console.log(`
===========================================
🚀 LAN Chat Room Server Started
===========================================
Server running at: http://localhost:${this.port}
WebSocket endpoint: ws://localhost:${this.port}/ws

Available on your network:
${this.getNetworkInterfaces().map(ip => `  http://${ip}:${this.port}`).join('\n')}

API Endpoints:
  POST /api/rooms - Create a room
  GET  /api/rooms/:id - Get room info
  POST /api/rooms/:id/join - Join room
  GET  /api/invite/:code - Validate invite
  GET  /api/stats - Server statistics

Press Ctrl+C to stop the server
===========================================
                `);

                resolve();
            });
        });
    }

    /**
     * Stop the server
     */
    stop() {
        return new Promise((resolve) => {
            console.log('Shutting down server...');
            
            // Close WebSocket server
            if (this.websocketServer) {
                this.websocketServer.shutdown();
            }

            // Close HTTP server
            this.server.close(() => {
                console.log('Server stopped');
                resolve();
            });
        });
    }

    /**
     * Get network interfaces for displaying available IPs
     */
    getNetworkInterfaces() {
        const os = require('os');
        const interfaces = os.networkInterfaces();
        const ips = [];

        for (const name of Object.keys(interfaces)) {
            for (const iface of interfaces[name]) {
                // Skip internal and non-IPv4 addresses
                if (!iface.internal && iface.family === 'IPv4') {
                    ips.push(iface.address);
                }
            }
        }

        return ips;
    }

    /**
     * Get server statistics
     */
    getServerStats() {
        const roomStats = this.roomManager.getStats();
        const wsStats = this.websocketServer.getStats();
        
        return {
            ...roomStats,
            websocket: wsStats,
            server: {
                port: this.port,
                uptime: process.uptime(),
                memory: process.memoryUsage(),
                networkInterfaces: this.getNetworkInterfaces()
            }
        };
    }
}

// Start server if this file is run directly
if (require.main === module) {
    const port = process.env.PORT || 3000;
    const server = new ChatServer(port);

    // Graceful shutdown
    process.on('SIGINT', async () => {
        console.log('\nReceived SIGINT, shutting down gracefully...');
        await server.stop();
        process.exit(0);
    });

    process.on('SIGTERM', async () => {
        console.log('\nReceived SIGTERM, shutting down gracefully...');
        await server.stop();
        process.exit(0);
    });

    // Start the server
    server.start().catch((error) => {
        console.error('Failed to start server:', error);
        process.exit(1);
    });
}

module.exports = ChatServer;